package com.water.devtool.define;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.water.devtool.BeanUtil;
import com.water.devtool.bean.FieldDefine;
import com.water.devtool.constant.BeanType;
import com.watermud.util.StringUtil;

/**
 * 实体模型对象
 * 
 * @author sun.lihua
 *
 */
@JsonIgnoreProperties(ignoreUnknown = true)
public class EntityBean extends DefineBean {
	private String code;
	private String javaName;
	private String packageName;
	@JsonIgnore
	private ModularBean modular;
	private List<FieldDefine> columns = new ArrayList<FieldDefine>();
	private String prefix;
	private String seqName;
	private String primaryKey;
	private boolean isAutoIncrement;
	private String dataSource;
	private String dbType;
	private String desc;
	private String orderSql;
	private boolean jspNeedDate = false;
	private boolean javaNeedDate = false;
	private boolean close;
	private boolean logicDelete;

	private String deleteField;
	private String deleteValue;

	// 暂时未用到classBean。还需要后续再看，是否需要独立的配置。比如配置方法等。
	private Map<String, ClassBean> classConfig = new HashMap<String, ClassBean>();

	private Map<String, Object> levelConfig = new HashMap<String, Object>();

	public boolean containClass(String name) {
		return classConfig.containsKey(name);
	}

	public void setDefault() {
		int index = code.indexOf("_");
		prefix = code.substring(0, index + 1);
		String codeTemp = code;
		if (StringUtils.isNotBlank(prefix)) {
			if (code.startsWith(prefix.toUpperCase())) {
				codeTemp = code.substring(prefix.length());
			}
		}
		javaName = StringUtil.capitalize(StringUtil.getJavaStyleName(codeTemp));
		logicDelete = false;
		deleteField = "valid_flag";
		deleteValue = "0";
	}

	public void init() {
		Set<String> keys = classConfig.keySet();
		for (String string : keys) {
			ClassBean b = classConfig.get(string);
			b.setEntity(this);
		}
	}

	public void addColumn(FieldDefine col) {
		if ("Date".equals(col.getJavaType())) {
			javaNeedDate = true;
		}
		if ("Date".equals(col.getJavaType()) && (!col.getCondition().equals("0") || !col.getInsertAble().equals("0"))) {
			jspNeedDate = true;
		}
		columns.add(col);
	}

	public ClassBean getClassConfig(String key) {
		return classConfig.get(key);
	}

	public void addClassConfig(String key) {
		classConfig.put(key, new ClassBean());
	}

	public void removeClassConfig(String key) {
		classConfig.remove(key);
	}

	@Override
	@JsonIgnore
	public BeanType getType() {
		return BeanType.ENTITY;
	}

	public String getJavaName() {
		return javaName;
	}

	public void setJavaName(String javaName) {
		this.javaName = javaName;
	}

	@JsonIgnore
	public ProjectBean getProject() {
		return modular.getProject();
	}

	public ModularBean getModular() {
		return modular;
	}

	public void setModular(ModularBean modular) {
		this.modular = modular;
	}

	public String getSeqName() {
		return seqName;
	}

	public void setSeqName(String seqName) {
		this.seqName = seqName;
	}

	@JsonIgnore
	public FieldDefine getPrimaryColumn() {
		for (FieldDefine fieldDefine : columns) {
			if (fieldDefine.getDbName().toUpperCase().equals(getPrimaryKey().toUpperCase())) {
				return fieldDefine;
			}
		}
		return null;
	}

	public String getPrimaryKey() {
		if (StringUtils.isBlank(primaryKey)) {
			return "id";
		}
		return primaryKey;
	}

	public void setPrimaryKey(String primaryKey) {
		this.primaryKey = primaryKey;
	}

	public boolean isAutoIncrement() {
		return isAutoIncrement;
	}

	public void setAutoIncrement(boolean isAutoIncrement) {
		this.isAutoIncrement = isAutoIncrement;
	}

	public String getDataSource() {
		return dataSource;
	}

	public void setDataSource(String dataSource) {
		this.dataSource = dataSource;
	}

	public String getDbType() {
		return dbType;
	}

	public void setDbType(String dbType) {
		this.dbType = dbType;
	}

	public String getDesc() {
		return desc;
	}

	public void setDesc(String desc) {
		this.desc = desc;
	}

	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}

	public String getPrefix() {
		return prefix;
	}

	public void setPrefix(String prefix) {
		this.prefix = prefix;
	}

	public String getPackageName() {
		return packageName;
	}

	public void setPackageName(String packageName) {
		this.packageName = packageName;
	}

	public Map<String, ClassBean> getClassConfig() {
		return classConfig;
	}

	public void setClassConfig(Map<String, ClassBean> classConfig) {
		this.classConfig = classConfig;
	}

	public List<FieldDefine> getColumns() {
		return columns;
	}

	public void setColumns(List<FieldDefine> columns) {
		this.columns = columns;
	}

	@JsonIgnore
	public boolean isUseDbGenerateId() {
		return isAutoIncrement || StringUtils.isNotBlank(BeanUtil.getSeqName(this));
	}

	@JsonIgnore
	public boolean isNeedInsert(String name) {
		if (isAutoIncrement && name.toUpperCase().equals(getPrimaryKey().toUpperCase())) {
			return false;
		}
		return true;
	}

	@JsonIgnore
	public boolean isNeedSetValue(String name) {
		if (isUseDbGenerateId() && name.toUpperCase().equals(getPrimaryKey().toUpperCase())) {
			return false;
		}
		return true;
	}

	@JsonIgnore
	public boolean hasDataSource() {
		return StringUtil.isNotNull(getTheDataSource());
	}

	@JsonIgnore
	public String getTheDataSource() {
		if (StringUtil.isNull(dataSource)) {
			return getProject().getDefaultDataSource();
		}
		return dataSource;
	}

	@JsonIgnore
	public String getInsertValue(String name) {
		if (name.toUpperCase().equals(getPrimaryKey().toUpperCase())) {
			String seq = BeanUtil.getSeqName(this);
			if (StringUtils.isNotBlank(seq)) {
				return seq + ".nextval";
			} else {
				return "?";
			}

		}
		return "?";
	}

	public Map<String, Object> getLevelConfig() {
		return levelConfig;
	}

	public Object getLevelConfig(String level) {
		return levelConfig.get(level);
	}

	public void addLevelConfig(String level, Object value) {
		levelConfig.put(level, value);
	}

	public void setLevelConfig(Map<String, Object> levelConfig) {
		this.levelConfig = levelConfig;
	}

	public String getOrderSql() {
		return orderSql;
	}

	public void setOrderSql(String orderSql) {
		this.orderSql = orderSql;
	}

	public boolean isJspNeedDate() {
		return jspNeedDate;
	}

	public void setJspNeedDate(boolean jspNeedDate) {
		this.jspNeedDate = jspNeedDate;
	}

	public boolean isClose() {
		return close;
	}

	public void setClose(boolean close) {
		this.close = close;
	}

	public boolean isJavaNeedDate() {
		return javaNeedDate;
	}

	public void setJavaNeedDate(boolean javaNeedDate) {
		this.javaNeedDate = javaNeedDate;
	}

	public boolean isLogicDelete() {
		return logicDelete;
	}

	public void setLogicDelete(boolean logicDelete) {
		this.logicDelete = logicDelete;
	}

	public String getDeleteField() {
		return deleteField;
	}

	public void setDeleteField(String deleteField) {
		this.deleteField = deleteField;
	}

	public String getDeleteValue() {
		return deleteValue;
	}

	public void setDeleteValue(String deleteValue) {
		this.deleteValue = deleteValue;
	}

	@JsonIgnore
	public String getContainDictCol() {
		for (FieldDefine fd : columns) {
			if (StringUtils.isNotBlank(fd.getCodeType()) && fd.getCodeType().indexOf(":") < 0) {
				return "1";
			}
		}
		return "0";
	}

	@JsonIgnore
	public String getDictCols() {
		List<String> a = new ArrayList<String>();
		for (FieldDefine fd : columns) {
			if (StringUtils.isNotBlank(fd.getCodeType()) && fd.getCodeType().indexOf(":") < 0) {
				a.add(fd.getName());
			}
		}
		return toParamStr(a);
	}

	@JsonIgnore
	public String getDicTypes() {
		List<String> b = new ArrayList<String>();
		for (FieldDefine fd : columns) {
			if (StringUtils.isNotBlank(fd.getCodeType()) && fd.getCodeType().indexOf(":") < 0) {
				b.add(fd.getCodeType());
			}
		}
		return toParamStr(b);
	}

	private String toParamStr(List<String> a) {
		StringBuilder str = new StringBuilder();
		str.append("new String[] { ");
		if (a != null) {
			int i = 0;
			for (String s : a) {
				if (i++ > 0) {
					str.append(",");
				}
				str.append(" \"");
				str.append(s);
				str.append("\"");
			}
		}
		str.append("}");
		return str.toString();
	}

	@JsonIgnore
	public String getIdType() {
		if (isAutoIncrement) {
			return "1";
		}
		return "0";
	}

	@JsonIgnore
	public int getSearchLineCols() {
		int i = 0;
		for (FieldDefine fd : columns) {
			if (fd.getCondition().equals("1")) {
				i++;
			}
		}
		if (i <= 4) {
			return i;
		} else if (i <= 6) {
			return 3;
		} else {
			return 4;
		}

	}

}
